package com.netty.rpc.register;

import com.netty.rpc.info.InvokeMsg;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by XiongMM on 2017/11/23.
 */
public class RegistryHandler extends ChannelInboundHandlerAdapter {

   public static ConcurrentHashMap<String,Object> registryMap = new ConcurrentHashMap<>();

   public List<String> classCache = new ArrayList<>();

   public RegistryHandler(){
       //服务扫描与发现
       scannerClass("com.netty.rpc.impl");
       //服务注册
       doRegistry();
   }

    private void doRegistry() {
       if(this.classCache.size() == 0){
           return ;
       }
       for(String className:classCache){
           try {
               Class<?> clazz = Class.forName(className);
               Class<?> interfaces = clazz.getInterfaces()[0];
               //System.out.println(interfaces.getName());//com.netty.rpc.api.ComputeApi
               registryMap.put(interfaces.getName(),clazz.newInstance());
           }catch (Exception ex){
               ex.printStackTrace();
           }

       }
    }

    private void scannerClass(String packageName) {
        URL url = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.","/"));
        File file = new File(url.getFile());
        for(File f : file.listFiles()){
            if(f.isDirectory()){
                scannerClass(packageName + "." + f.getName());
            }else{
                classCache.add(packageName + "."+f.getName().replace(".class",""));
            }
        }
    }

    //读取服务方，返回的结果
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{
       Object result = new Object();
        InvokeMsg invokeMsg = (InvokeMsg) msg;
        //服务发现
        if(registryMap.containsKey(invokeMsg.getClassName())){
            Object clazz = registryMap.get(invokeMsg.getClassName());
            Method method = clazz.getClass().getMethod(invokeMsg.getMethodName(),invokeMsg.getParamType());
            result = method.invoke(clazz,invokeMsg.getParameters());
        }
        //结果返回
        ctx.write(result);
        ctx.flush();
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("server exception is general ~");
    }
}
